#ifndef dialog_h__
#define dialog_h__

#include "basic_window.hpp"
#include "data_exchange.hpp"

namespace winboost {
   namespace windows {

class dialog : public basic_window
{
public:
   explicit dialog(UINT id, HWND hparent=NULL);

   int show_modal();
   void close(int exit_code);
   void ok();
   void cancel();

   //-------------------------------------------
   // data exchange
   //-------------------------------------------
   void transfer_data(transfer_direction d);
   data_exchange& dex(void) const { return const_cast<data_exchange&>(m_dex); }

   virtual bool is_dialog(void) const { return true; }

protected:
   virtual bool pre_translate_message(UINT message, WPARAM wparam, LPARAM lparam);

private:
   UINT m_id;
   HWND m_hparent;
   data_exchange m_dex;

   static INT_PTR CALLBACK dlg_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
   LRESULT on_init_dialog(const winboost::events::message& e);
};


inline dialog::dialog(UINT id, HWND hparent/*=NULL*/):
  m_id(id)
, m_hparent(hparent)
{
   set_message_handler(WM_INITDIALOG, boost::bind(&dialog::on_init_dialog, this, _1));

   if(hparent == NULL)
   {
      winboost::state::state_ptr_type pstate = _the_module.get_thread_state();
      if(pstate->m_pwnd_main)
         m_hparent = pstate->m_pwnd_main->handle();
   }
}

inline int dialog::show_modal()
{
   hook_window(this);

   HINSTANCE hinst = instance_handle();
   int exit_code = ::DialogBox(hinst, MAKEINTRESOURCE(m_id), m_hparent, dialog::dlg_proc);
   unhook_window();

   return exit_code;
}

inline void dialog::close(int exit_code)
{
   ::EndDialog(win_handle::handle(), exit_code); 
}

inline void dialog::ok() 
{
   ::EndDialog(win_handle::handle(), IDOK);
}

inline void winboost::windows::dialog::cancel() 
{
   ::EndDialog(win_handle::handle(), IDCANCEL);
}

inline void dialog::transfer_data(transfer_direction d)
{
   if(d == to_variable)
      m_dex.transfer_to(win_handle::handle());
   else
      m_dex.transfer_from(win_handle::handle());
}

inline bool dialog::pre_translate_message(UINT message, WPARAM wparam, LPARAM lparam)
{ 
   switch(message)
   {
   case WM_SYSCOMMAND:
      {
         WORD w = LOWORD(wparam);
         switch(w)
         {
         case SC_CLOSE:
            cancel();
            return true;
         }
      }
      break;
   }
   return false;
}   

inline INT_PTR CALLBACK dialog::dlg_proc(HWND hdlg, UINT message, WPARAM w, LPARAM l)
{
   if(message == WM_DESTROY)
   {
      if(check_exit_state(hdlg, message))
      {
         // if main window destroyed, then
         // exit program
         ::PostQuitMessage(0);
         return 0L;
      }
   }

   event_router* pwnd = dynamic_cast<event_router*>(_the_module.find_window(hdlg));
   pwnd->route(message, w, l);
   return (INT_PTR)FALSE;
}

inline LRESULT dialog::on_init_dialog(const winboost::events::message& e)
{
   transfer_data(to_control);
   return 0;
}

   }
}

#endif // dialog_h__